package org.myorg.v3;


public abstract class Fc3 {
	
	double low = Double.NEGATIVE_INFINITY;
	double high = Double.POSITIVE_INFINITY;
	
	public double best = Double.POSITIVE_INFINITY;
	public double[] data = null;
	boolean[] mark = null;
	int count = 0;
	
	public abstract double fc(double[] tmp);
	//public abstract void caculate(Gene3 person);
	//public abstract void caculate(Gene3 person, double begin, double all);
	
	public void caculate(Gene3[] persons) {
		for (Gene3 gene:persons) {
			caculate(gene);
		}
	}
	public void caculate(Gene3[] persons, double begin, double all) {
		for (Gene3 gene:persons) {
			caculate(gene, begin, all);
		}
	}
	public void caculate(Gene3[] persons, double all) {
		for (Gene3 gene:persons) {
			caculate(gene, all);
		}
	}
	
	//public abstract double org_value(Gene3 persion);
	//public abstract double org_value(Gene3 persion, double begin, double all); 
	
	
	public void caculate(Gene3 ps) {
		// TODO Auto-generated method stub
		/**
		 * add your function here
		 * for example: f(x)= sin(x) x [0, 3.14] 
		 * set the genetic length is 1, so the mapping relation is
		 * [0, 1] -> [0, 3.14]
		 */
		FGene3 person = (FGene3)ps;
		person.setFitness(-org_value(ps));
	}



	public double org_value(Gene3 ps) {
		FGene3 gene = (FGene3)ps;
		//double x = (high - low)*gene.geneAt(0) + low;
		//double tmp = (Math.PI + 100)*x/100 - 100;

		
		double[] tmp = new double[gene.getGene().length];
		for (int i = 0; i < gene.getGene().length; i++ ) {
			tmp[i] = (high - low)*gene.geneAt(i) + low;
		}
		
		return fc(tmp);
		
	}
	
	
	public double org_value(Gene3 ps, double begin, double all) {
		FGene3 gene = (FGene3)ps;
		//double x = (high - low)*gene.geneAt(0) + low;
		//double tmp = (Math.PI + 100)*x/100 - 100;

		int gl = gene.getGene().length;
		//double begin = 0;
		double seg = 1;
		double[] tmp = new double[gl];
		
		
		//每个x分割成多少段就可以达到分段的要求
		while (Math.pow(seg, gl) < all) {
			seg++;
		}
		
		//有多少维的x需要分割
		//int tr = (int)Math.pow(all, 1d/(double)seg);
		int tr = (int)(Math.log(all)/Math.log((double)seg));
		//int[] x_begin = new int[tr];
		int x_begin = 0;
		//for (int i = 0; i < ; )
		//begin = (int)(seg/2);
		/*
		 * 分割成右闭左开区间
		 */
		
		//System.out.println("orginal gene is " + gene.geneAt(0));
/*		for (int i = 0; i < tr; i++ ){
			x_begin = (int)begin%(int)seg;
			begin = (int) (begin/seg);
			if ( x_begin != (seg -1) && gene.geneAt(i) == 1d) {
				gene.setGene(0, 0d);
			}
			
			tmp[i] = ((high - low)/seg)*gene.geneAt(i) + 
			low + (high-low)*((double)x_begin/seg);
				
		}
		
		for (int i = tr ; i < gene.getGene().length; i++ ) {
			tmp[i] = (high - low)*gene.geneAt(i) + low;
		}*/
		//int l = gene.getGene().length;
/*		System.out.println("segment:");*/
		for (int i = gl - 1; i >= gl - tr; i-- ){
			
			x_begin = (int)begin%(int)seg;
			begin = (int) (begin/seg);
			if ( x_begin != (seg -1) && gene.geneAt(i) == 1d) {
				gene.setGene(0, 0d);
			}

			tmp[i] = ((high - low)/seg)*gene.geneAt(i) + 
			low + (high-low)*((double)x_begin/seg);
/*			System.out.print("seg" + i + "x_b" + x_begin 
					+ "seg" + seg + "v" + ((double)x_begin/seg) + "tmp" + tmp[i] + " ");*/
		}
		
		for (int i = 0 ; i < gl - tr; i++ ) {
/*			System.out.print("nonseg" + i + " ");*/
			tmp[i] = (high - low)*gene.geneAt(i) + low;
		}
/*		System.out.print("\n");*/
		//System.out.println("tmp[0] " + tmp[0] + " and gene is " + gene.geneAt(0));
		
		return fc(tmp);
		
	}
	
	public double org_value(Gene3 ps, double all) {
		FGene3 gene = (FGene3)ps;
		//double x = (high - low)*gene.geneAt(0) + low;
		//double tmp = (Math.PI + 100)*x/100 - 100;

		int gl = gene.getGene().length;
		double begin = 0;
		double seg = 2;
		double[] tmp = new double[gl];
		
		while (Math.pow(seg, gl) < all) {
			seg++;
		}
		begin = (int)(seg/2);
		/*
		 * 分割成右闭左开区间
		 */
		int tr = (int)Math.pow(all, 1/(double)seg);
		//System.out.println("orginal gene is " + gene.geneAt(0));
/*		for (int i = 0; i < tr; i++ ){
			if ( begin != (seg -1) && gene.geneAt(i) == 1d) {
				gene.setGene(0, Math.random());
			}
			
			tmp[i] = ((high - low)/seg)*gene.geneAt(i) + 
			low + (high-low)*((double)begin/seg);
				
		}
		
		for (int i = tr ; i < gene.getGene().length; i++ ) {
			tmp[i] = (high - low)*gene.geneAt(i) + low;
		}*/
		
		for (int i = gene.getGene().length - 1; i > gene.getGene().length - tr; i-- ){
			if ( begin != (seg -1) && gene.geneAt(i) == 1d) {
				gene.setGene(0, Math.random());
			}
			
			tmp[i] = ((high - low)/seg)*gene.geneAt(i) + 
			low + (high-low)*((double)begin/seg);
				
		}
		
		for (int i = 0 ; i < gene.getGene().length - tr; i++ ) {
			tmp[i] = (high - low)*gene.geneAt(i) + low;
		}
		
		//System.out.println("tmp[0] " + tmp[0] + " and gene is " + gene.geneAt(0));
		
		return fc(tmp);
		
	}

	public void caculate(Gene3 ps, double begin, double all) {

		FGene3 person = (FGene3)ps;
		person.setFitness(-org_value(ps, begin, all));
	
	}
	
	public void caculate(Gene3 ps, double all) {

		FGene3 person = (FGene3)ps;
		person.setFitness(-org_value(ps, all));
	
	}
	
	/*
	 * return -1 not record
	 * 1 record
	 * 0 break
	 */
	
	public int is_r(Gene3 g) {
		
		int res = -1;

		if (count < data.length && !mark[count] && org_value(g) < data[count] ) {
			res = 1;
			mark[count] = true;
			count++;
			if (count == data.length) {
				res = 0;
			}
		}


		return res;
	}

	/*
	 * return -1 not record
	 * 1 record
	 * 0 break
	 */
	
	public int is_r(Gene3 g, double begin, double all) {
		
		int res = -1;

		if (count < data.length && !mark[count] && org_value(g, begin, all) < data[count] ) {
			res = 1;
			mark[count] = true;
			count++;
			if (count == data.length) {
				res = 0;
			}
		}


		return res;
	}
	
	//public abstract void init();
}